﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing.Drawing2D;

namespace PControl
{
    /// <summary>
    /// 自定义垂直进度条显示控件
    /// </summary>
    public partial class VerticalProgressBar : UserControl
    {
        /// <summary>
        /// 控件最大值
        /// </summary>
        private int maximum = 100;
        /// <summary>
        /// 控件最大值
        /// </summary>
        private int minimum = 0;
        /// <summary>
        /// 控件步进值
        /// </summary>
        private int step = 1;
        /// <summary>
        /// 控件当前值
        /// </summary>
        private int currentValue = 50;
        /// <summary>
        /// 控件圆角半径
        /// </summary>
        private int radius = 15;
        /// <summary>
        /// 控件背景色
        /// </summary>
        private Color backColor = Color.LightGray;
        /// <summary>
        /// 控件前景色
        /// </summary>
        private Color foreColor = Color.Green;

        /// <summary>
        /// 默认构造方法
        /// </summary>
        public VerticalProgressBar()
        {
            InitializeComponent();
            // ***** avoid flickering
            this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
            this.SetStyle(ControlStyles.UserPaint, true);
            this.SetStyle(ControlStyles.DoubleBuffer, true);
        }
        [Description("get or set maximun value of this vertical progressbar\n获取或设置垂直进度条的最大值")]
        [Category("VerticalProgressBar")]
        [RefreshProperties(RefreshProperties.All)]
        public int Maximum
        {
            get
            {
                return maximum;
            }
            set
            {
                maximum = value;
                if (maximum < minimum)
                    minimum = maximum;
                if (maximum < currentValue)
                    currentValue = maximum;
                Invalidate();
            }
        }
        [Description("get or set minimun value of this vertical progressbar\n获取或设置垂直进度条的最小值")]
        [Category("VerticalProgressBar")]
        [RefreshProperties(RefreshProperties.All)]
        public int Minimum
        {
            get
            {
                return minimum;
            }
            set
            {
                minimum = value;
                if (minimum > maximum)
                    maximum = minimum;
                if (minimum > currentValue)
                    currentValue = minimum;
                Invalidate();
            }
        }
        [Description("get or set the step of this vertical progressbar\n获取或设置垂直进度条单步增量")]
        [Category("VerticalProgressBar")]
        [RefreshProperties(RefreshProperties.All)]
        public int Step
        {
            get
            {
                return step;
            }
            set
            {
                step = value;
            }
        }
        [Description("get or set the value of this vertical progressbar\n获取或设置垂直进度条当前值")]
        [Category("VerticalProgressBar")]
        [RefreshProperties(RefreshProperties.All)]
        public int Value
        {
            get
            {
                return currentValue;
            }
            set
            {
                currentValue = value;
                if (currentValue > maximum)
                    currentValue = maximum;
                if (currentValue < minimum)
                    currentValue = minimum;
                Invalidate();
            }
        }
        [Description("get or set the corner radius of this vertical progressbar\n获取或设置垂直进度条圆角半径")]
        [Category("VerticalProgressBar")]
        [RefreshProperties(RefreshProperties.All)]
        public int Radius
        {
            get
            {
                return radius;
            }
            set
            {
                radius = value;
                if (this.Height >= this.Width)
                {
                    if (radius > this.Width / 2)
                    {
                        radius = this.Width / 2;
                    }
                }
                else
                {
                    if (radius > this.Height / 2)
                    {
                        radius = this.Height / 2;
                    }
                }
                Invalidate();
            }
        }
        [Description("get or set the backcolor of this vertical progressbar\n获取或设置垂直进度条的背景色")]
        [Category("VerticalProgressBar")]
        [RefreshProperties(RefreshProperties.All)]
        public override System.Drawing.Color BackColor
        {
            get
            {
                return backColor;
            }
            set
            {
                backColor = value;
                Invalidate();
            }
        }
        [Description("get or set the forecolor of this vertical progressbar\n获取或设置垂直进度条的前景色")]
        [Category("VerticalProgressBar")]
        [RefreshProperties(RefreshProperties.All)]
        public override System.Drawing.Color ForeColor
        {
            get
            {
                return foreColor;
            }
            set
            {
                foreColor = value;
                Invalidate();
            }
        }
        /// <summary>
        /// 显示值增加一个步进值
        /// </summary>
        public void PerformStep()
        {
            currentValue += step;

            if (currentValue > maximum)
                currentValue = maximum;
            if (currentValue < minimum)
                currentValue = minimum;

            Invalidate();
        }
        /// <summary>
        /// 控件显示值增加value
        /// </summary>
        /// <param name="value"></param>
        public void Increment(int value)
        {
            currentValue += value;

            if (currentValue > maximum)
                currentValue = maximum;
            if (currentValue < minimum)
                currentValue = minimum;

            Invalidate();
        }

        #region 绘制圆角
        public void SetWindowRegion()
        {
            if (radius > 0)
            {
                System.Drawing.Drawing2D.GraphicsPath FormPath;
                FormPath = new System.Drawing.Drawing2D.GraphicsPath();
                Rectangle rect = new Rectangle(0, 0, this.Width, this.Height);//this.Left-10,this.Top-10,this.Width-10,this.Height-10);                 
                FormPath = GetRoundedRectPath(rect, radius);
                this.Region = new Region(FormPath);
            }
        }

        private GraphicsPath GetRoundedRectPath(Rectangle rect, int radius)
        {
            Rectangle arcRect = new Rectangle(rect.Location, new Size(radius, radius));
            GraphicsPath path = new GraphicsPath();
            //   左上角   
            path.AddArc(arcRect, 180, 90);
            //   右上角   
            arcRect.X = rect.Right - radius;
            path.AddArc(arcRect, 270, 90);
            //   右下角   
            arcRect.Y = rect.Bottom - radius;
            path.AddArc(arcRect, 0, 90);
            //   左下角   
            arcRect.X = rect.Left;
            path.AddArc(arcRect, 90, 90);
            //path.AddPie(0, 0, radius * 2, radius * 2, 180, 90);//左上角
            //path.AddPie(rect.Right - radius * 2, 0, radius * 2, radius * 2, 270, 90);//右上角
            //path.AddPie(rect.Right - radius * 2, rect.Bottom - radius * 2, radius * 2, radius * 2, 0, 90);//右下角
            //path.AddPie(0, rect.Bottom - radius * 2, radius * 2, radius * 2, 90, 90);//左下角
            //Rectangle Rect = new Rectangle(radius, 0, rect.Width - 2 * radius, rect.Height);
            //path.AddRectangle(Rect);
            //Rect = new Rectangle(0, radius, radius, rect.Height - 2 * radius);
            //path.AddRectangle(Rect);
            //Rect = new Rectangle(rect.Width - radius, radius, radius, rect.Height - 2 * radius);
            //path.AddRectangle(Rect);
            //path.CloseFigure();
            return path;
        }
        #endregion

        private void VerticalProgressBar_Load(object sender, EventArgs e)
        {
            SetWindowRegion();
        }

        private void drawBorder(Graphics graphics)
        {
            Color color = ControlPaint.Dark(this.BackColor);
            Pen pen = new Pen(color, 1);
            //graphics.DrawLine(pen, this.Width, 0, 0, 0);
            //graphics.DrawLine(pen, 0, 0, 0, this.Height);
            //graphics.DrawLine(pen, 0, this.Height-1, this.Width, this.Height-1);
            //graphics.DrawLine(pen, this.Width-1, this.Height, this.Width-1, 0);
        }

        //绘制进度
        public void drawProgress(Graphics graphics)
        {
            //画背景
            graphics.FillRectangle(new SolidBrush(backColor), 0, 0, this.Width, this.Height);

            if ((minimum == maximum) || (currentValue - minimum) == 0)
                return;
            int width = this.Width;		// the bar width
            int height;		            // the bar height
            int x = 0;				    // the bottom-left x pos of the bar
            int y = this.Height;			// the bottom-left y pos of the bar
            height = (currentValue - minimum) * y / (maximum - minimum);

            Color boardColor = Color.FromArgb(0, 211, 40);
            Color centerColor = Color.FromArgb(195, 210, 210);
            Color[] colors = {boardColor,centerColor,boardColor };
            float[] position = { 0.0f, 0.03f, 1.0f };
            ColorBlend blend = new ColorBlend();
            
            blend.Positions = position;
            Rectangle rect;
            LinearGradientBrush brush;
            if (height != 0)
            {
                blend.Colors = colors;
                rect = new Rectangle(x, y - height, width, height);
                brush = new LinearGradientBrush(rect, boardColor, boardColor, 0, false);
                brush.InterpolationColors = blend;
                graphics.FillRectangle(brush, rect);
            }
            if (y != height)
            {
                boardColor = Color.FromArgb(149, 149, 149);
                colors[0] = colors[2] = boardColor;
                blend.Colors = colors;
                rect = new Rectangle(x, 0, width, y - height);
                brush = new LinearGradientBrush(rect, boardColor, boardColor, 0, false);
                brush.InterpolationColors = blend;
                graphics.FillRectangle(brush, rect);
            }
        }
        /// <summary>
        /// 重装控件重绘方法
        /// </summary>
        /// <param name="e"></param>
        protected override void OnPaint(PaintEventArgs e)
        {
            Graphics graphics = e.Graphics;
            drawProgress(graphics);
            drawBorder(graphics);
            SetWindowRegion();
            base.OnPaint(e);
        }
        /// <summary>
        /// 控件大小改变事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void OnSizeChanged(object sender, EventArgs e)
        {
            base.OnSizeChanged(e);
            Invalidate();
        }

        private void VerticalProgressBar_Resize(object sender, EventArgs e)
        {
            //base.OnResize(e);
            Invalidate();
        }
    }
}
